home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / tools / gcc / gcc270_base.lha / gnu / Apurify / doc / APurify.doc next >
Encoding:
Text File  |  1995-08-23  |  26.2 KB  |  575 lines

  1.                     APurify v1.2.1
  2.                     --------------
  3.  
  4.                  GCC version.
  5.  
  6.                (c) by Samuel DEVULDER
  7.                  August 1995
  8.  
  9.                Samuel.Devulder@info.unicaen.fr
  10.  
  11. DESCRIPTION (SHORT):
  12. --------------------
  13.     APurify is a program that allows you to detect bad accesses  to  memory
  14.     of your programs without any kind of specific external  devices  (MMU).
  15.     It avoids bugs due to accessing memory not owned by your program.
  16.  
  17.     This is a port for APurify v1.1 on Aminet/dev/debug for GCC. I've  done
  18.     some little improvements so that it is not exactly the same as v1.1. It
  19.     may be full of bugs, so be carefull. I must add also that the port    was
  20.     harder than I thought to do (it's hard to port on  a  unkwown  compiler
  21.     with a strange syntax for assembler !).
  22.  
  23. SYNOPSIS:
  24. --------
  25.     Usage: APurify [-revinfo] [flags] <inputfile> [-o <outputfile>]
  26.  
  27.     Where flags can be:
  28.        -br<Ax>    To set the base register
  29.        -tb    To test memory referenced through base register
  30.        -ts    To test memory referenced through stack register
  31.        -tl    To test memory referenced through local stack frame
  32.        -tp    To test pea instructions
  33.        -?,?,-h    To display this usage
  34.  
  35.     Flags can be anywhere on the command line and may be  merged  together.
  36.     But take care that flags that need an extra argument appear in the last
  37.     position. Thus "-tsoPROG.s" is good  and  will  output  a  file  called
  38.     "PROG.s" while "-otsPROG.s" is wrong and  will  output  a  file  called
  39.     "tsPROG.s" ! Here is a short description of arguments and flags:
  40.  
  41.     -revinfo:    This displays informations  about APurify  (name,  size and
  42.         date of modules and number of  compilation  done  for  that
  43.         version).
  44.  
  45.     -br<Ax>:    This  sets  the  base  register  used  to  reference memory
  46.         in SMALL_DATA model. Usually A4 is used  for  that  perpose
  47.         and that's the default. If A5  is  used  instead  then  add
  48.         -brA5 on your command line.
  49.  
  50.     -tb:    This enable APurify to check all referenced  memory through
  51.         the base register (see -br). If you are using a  SMALL_DATA
  52.         model, add this flag on  your  command    line.  By  default,
  53.         APurify won't check  memory  referenced  through  the  base
  54.         register.
  55.  
  56.         NOTE: for safest check, you should always use that  option,
  57.         even if you're not in smalldata model (A4 may  be  used  as
  58.         a temporary register in that case).
  59.  
  60.     -ts:    This  enable  APurify to  check memory referenced  by stack
  61.         pointer (SP or A7). By default  APurify  won't  check  such
  62.         memory accesses (to reduce the code size and  increase  the
  63.         runtime speed). That option will detect when  you  have  no
  64.         more room on your stack (stack overflow).
  65.  
  66.     -tl:    This enable APurify to check  memory  referenced   by local
  67.         stack pointer (the one that is link'ed and  unlink'ed  when
  68.         enterring and exiting a C-function). By  default,  this  is
  69.         switch off. This  option  allow  APurify  to  detect  stack
  70.         overflow.
  71.  
  72.     -tp:    This enable APurify to check indirect  adresses pushed onto
  73.         the stack by using a pea. By  default  this  is  off.  When
  74.         used, that option will check things like "pea  a2@(10)"  or
  75.         the like. This can help  you  with  memory  accessed  by  a
  76.         pointer in a code that has not been APurify'ed. For example
  77.         this is usefull  for  things  like  fread(&ptr[10],10,1,fp)
  78.         because in that case the "pea a2@(10)" used to push on  the
  79.         stack &ptr[10] will be checked and if ptr[10] is not  owned
  80.         by your program, you'll get an APurify error.  Please  note
  81.         that this may no work all the time  since  &ptr[0]  can  be
  82.         translated as "movel a0,sp@-" which  won't be checked.
  83.  
  84.     -o <outputfile>
  85.         This specifies the name of the outputfile. If  ommited    the
  86.         outputfile will be the same as the inputfile (source file).
  87.  
  88.     -?
  89.     -h
  90.     ?:        Obvious option.
  91.  
  92. DESCRIPTION (A BIT LONGER):
  93. --------------------------
  94.     As a general rule, at the microprocessor level, there is  two  kind
  95.     of ways to access memory. There is direct access and indirect access to
  96.     memory. For example, in C, direct access can be viewed as accessing  to
  97.     global variables. Indirect access corresponds  to  accessing  an  array
  98.     value. More precisely, direct access corresponds to reading or  writing
  99.     a variable whose address is known at compilation  time  (or  since  the
  100.     loading of the program into the memory). Indirect access  is  used    for
  101.     variables whose adress is dynamicaly determined  by  the  program.    For
  102.     example, if p is a pointer to an array allocated by malloc(), *p is  an
  103.     indirect access. Such an access occur also in case of instruction  like
  104.     T[i] where T is a global array, because the  address  of  T[i]  is    not
  105.     known at compilation time, since it depends on the index value i. Using
  106.     indirect access to memory is called indirection.
  107.  
  108.     A regular program must not access memory not owned by it. That kind
  109.     of access can be qualified as illegal.
  110.  
  111.     Illegal direct access  to   memory  is    not  possible, because     by
  112.     definition, only global  variables can be  accessed that  way and those
  113.     variables belongs obviously to the program    (except for code written in
  114.     assembly   language   that    references  absolute   values, for example:
  115.     "btst  #6,$bfe001"; but that  kind of  code  is not a  good programming
  116.     :-)). So we can assume that direct access to memory is always right.
  117.  
  118.     On the other hand,  it is sure    that indirect access to  memory can
  119.     be illegal.  Many bugs are made by    overstepping array  boundaries.  If
  120.     that oversteppings are  in reading a value, there  is not much  trouble
  121.     for over running tasks (it is an error inside your  task); but if it is
  122.     in writing you may directly interfere with other tasks and big mess can
  123.     happen (total breakdown of the system).
  124.  
  125.     APurify works on  that kind of access  by verifying the validity of
  126.     indirect access to memory. It remebers the memory that was allocated by
  127.     the program and check the integrity of  each access. One can think that
  128.     makes a lot of tests ! Well, yes, but APurify is  not  designed  to  be
  129.     used in the general use of programs; just  in  test  phases.  Moreover,
  130.     indirections  do  no  occur  very  often  actually.  Only    array-based
  131.     variables produces indirections.  Thus,  the  variables  on  the  stack
  132.     --although being accessed by  indirection--  are  not  checked  because
  133.     their access is always safe (at least if there is no stack overflow !).
  134.     Also, in SMALL_DATA model, global  variables  access  is  done  through
  135.     indirection, but they are not checked.
  136.  
  137.     If an illegal access is found, APurify displays an error message on
  138.     the error stream of the program (have a look at the full  justification
  139.     of the output when using verbose mode :^). There is two kind of illegal
  140.     accesses. Some are accesses  to  memory  that  doesn't  belong  to  the
  141.     program (it is called  an  access  between  blocks),  some  others  are
  142.     accesses to a part of memory owned by a program and an other  part    not
  143.     owned by it (it is an overstepping  of  a  block).  You  can  see  this
  144.     visually: If [ 1 ] and [ 2 ] represent  two  blocks  allocated  by    the
  145.     program and ( 3 ) the memory accessed, then
  146.  
  147.          ---- [ 1 ] ---- ( 3 ) ---- [ 2 ] ---->
  148.         0                       increasing address
  149.  
  150.     corresponds to the first kind of illegal access and
  151.  
  152.              ---- [ 1 ( ] 3 ) ---- [ 2 ] ----->
  153.     or
  154.              ---- [ 1 ] ---- ( 3 [ ) 2 ] ----->
  155.  
  156.     corresonds to the second kind of access. The first kind is very  common
  157.     but the second is quite rare (it's rather a misaligment problem).
  158.  
  159.     APurify has two output modes. One is verbose an tries to  give    lot
  160.     of informations by using words. The other one is more brief  and  gives
  161.     you the same informations but you'll have to decode them.
  162.  
  163.     When APurify starts and ends, it outputs  the  date/time.  This  is
  164.     useful if you are using logfiles. With that, you can keep all your logs
  165.     in a  single  file    and  retrieve  any  execution  with  it's  date  of
  166.     execution.
  167.  
  168.     In case of an error, APurify displays some  text.  The    first  line
  169.     looks like this one:
  170.  
  171.     **** APURIFY ERROR ! [$<N1>(<N2>) <ATTR> (<TEXT1>)] <TEXT2>:
  172.  
  173.     That line represent  the  accessed    memory.  <N1>  is  the    hexadecimal
  174.     address accessed. <N2> is the length of the access (in decimal). <ATTR>
  175.     represents the type of acess. <TEXT1> allows you to find where in  your
  176.     code the illegal accessed had happened. <TEXT2> describe  the  kind  of
  177.     illegal access.
  178.  
  179.     If the length (<N1>) is 1, then it was a byte access. 2 stands  for
  180.     a short access,  4    for  a    int/long  and  >4  for    movem  instruction.
  181.     Attributes, <ATTR>, can be "R--" or "-W-". The first one represents  an
  182.     access in reading a value and the second an access in writing a value.
  183.  
  184.     The text <TEXT1> look like this:
  185.  
  186.         <NAME>, PC=$<PC#> HUNK=$<HUNK#> OFFSET=$<OFF#>
  187.  
  188.     <NAME> is the name of the subroutine where the  error  occured.  It  is
  189.     always displayed (even if it is a "static" one). The rest of  the  line
  190.     can be partially displayed, showing as much informations as APurify can
  191.     get. <PC#> is a hexadecimal address pointing to  the  instruction  that
  192.     produced the error. <HUNK#> and <OFF#> are    the  hunk  number  and    the
  193.     relative offset of <PC#>. Using <HUNK#> and <OFF#> and a  disassembler,
  194.     you can very easilly find where your code is bad (BTW, I use dobj  from
  195.     netdcc, (c) by Matt Dillon). Please note  that  <PC#>  can  point  some
  196.     instruction before the faultly one. In that case, it will  point  to  a
  197.     PEA followed by a JSR. As those instructions does not  belong  to  your
  198.     code (they are APurify stuff), the involved instruction  is  the  third
  199.     one. That will happen only if  an  instruction  references    memory    two
  200.     times and if the first access is wrong. It is a little bit annoying but
  201.     it is better than nothing and it is quite rare :-).
  202.  
  203.     The remaining lines show the context  of  the  illegal    access.  It
  204.     gives you informations about the  surronding  memory  blocks  owned  by
  205.     your program. Each    block  is  displayed  according  to  the  following
  206.     pattern:
  207.  
  208.                [$<N1>(<N2>) <ATTR> (<TEXT>)]
  209.  
  210.     where <N1> is the hexadecimal address of the beginning  of    the  block,
  211.     <N2> its length (in decimal). Note that  the  length  may  seem  to  be
  212.     longer than the one allocated by malloc() and  the  address  may  point
  213.     before the one you obtained via malloc(). This is not wrong !  In  fact
  214.     you must know that the malloc() subroutine may  add  some  informations
  215.     (like an double-chained list or the length of the  allocation)  to  the
  216.     block you've requested. Those extra informations  are  put  before  the
  217.     address you recieve. That explain this behavior.  In  this    version  of
  218.     APur.lib, this takes 12 ($C) extra bytes. So if you allocate 10  bytes,
  219.     don't be suprised if APurify thinks you've requested 22 bytes.
  220.  
  221.     <ATTR> are 3 status characters RWS
  222.  
  223.     where R means: read-enable block
  224.           W means: write-enable block
  225.           S means: system block (block not controlled by the program).
  226.  
  227.     If one access is forbidden, the letter '-' replaces  the  corresponding
  228.     character. <TEXT> is actually  the    name  of  the  procedure  that    has
  229.     allocated the block. If it ends with "*" that block was allocated by  a
  230.     call to a subroutine not parsed by APurify during the execution of    the
  231.     one indicated (a library call, maybe).
  232.  
  233.     With each block you can find an offset. That offset is the distance
  234.     between that block and the faultly address. In verbose  mode,  you    can
  235.     see some text explaining things about the relative position of a  block
  236.     and the accessed memory. In non-verbose  mode  you    can  just  see    the
  237.     offsets followed by the blocks. The shorter offset is  displayed  first
  238.     since that block is the one that is more likely overstepped.
  239.  
  240.     When an illegal writing occur (the only dangerous thing you can  do
  241.     by indirection, indeed), APurify tells you    to  that  error  is  really
  242.     dangerous and asks if you wish to stop your program. If  you  wish    so,
  243.     exit() is called. You can also ignore that error  or  ignore  all  such
  244.     errors (but then you'll surely meet the guru !).
  245.  
  246.     APurify checks the memory allocated but not freed by  the  program.
  247.     (in fact, it detects non deallocated-blocks on library-closing time).
  248.  
  249.     It  knows  about  memory  location  independant  of   the   program
  250.     execution. That is to say, the first kilobyte of memory  that  contains
  251.     interrupt vectors of the 680x0 processor, the program segments and    the
  252.     stack. Accessing to those blocks will not be illegal. They    got  the  S
  253.     attribute (for SYSTEM blocks).
  254.  
  255.     It takes into  account    memory    block  allocated  by  malloc()  and
  256.     AllocMem(), and indirect allocated block (by OpenScreen() for example).
  257.     But I did not test the last kind of allocation. Anyway,  it  should  be
  258.     ok, because APurify patches AllocMem()  &  FreeMem()  entries.  Thus  a
  259.     program can access to the bitplanes of one of its screen without error.
  260.  
  261.     If  the  program  makes  a  legal  access,   but   attributes    are
  262.     incompatible  with    the  access-kind,  a  protection-error    message  is
  263.     displayed. Actually only the first    kilobyte  is  read/write-protected.
  264.     But it may change in the future.
  265.  
  266.     In order to speed up block  searching,    APurify  uses  a  cache  of
  267.     recently accessed blocks. Thus, even if there  is  a  large  amount  of
  268.     memory blocks, execution should not be slowed down too much. (but I must
  269.     say I doubt it is efficient enough).
  270.  
  271. HOW TO USE APURIFY:
  272. ------------------
  273.     One can see APurify as a pre-assembler. It must be used on assembly
  274.     language sourcefile just before the assembler takes place. It scan    the
  275.     file and change it a bit so that APur.a can be used.
  276.  
  277.     Normal way to use it for a C program is to:
  278.  
  279.     - compile C sourcefiles and leave assembly language source (.s).
  280.     - use APurify on each .s file.
  281.     - compile your .s file to get a .o file
  282.     - link all .o files together with APur.a.
  283.  
  284.     For example, using gcc on prog.c it gives
  285.  
  286.     CLI> gcc -g prog.c -o prog.s -S
  287.     CLI> APurify -tb prog.s
  288.     CLI> gcc -g prog.s -o prog -lAPur
  289.  
  290.     As you can see, APurify needs no change to your C  files  to  be  used.
  291.     However, the library must be opened by calling AP_Init() in the  main()
  292.     function. Note that now, you need not call AP_Close() anymore (even  if
  293.     you can still call it but for nothing (it is  automatically  called  on
  294.     exit()). But do not use Exit() to abort your  program,  I  think  it'll
  295.     crash if  APurify  is  running.  If  you  must  use  Exit()  then  call
  296.     AP_Close() just before calling Exit(). The explantion is simple:  since
  297.     some system functions are patched, if a program exits  without  closing
  298.     the library, those patch will be corruped, pointing to a code  that  is
  299.     nomore in memory and you'll  meet  the  guru  (ie:  the  computer  will
  300.     crash)... (You've been warned :-).
  301.  
  302.     If you forget to open the library, a warning message will tell    you
  303.     about that and the program will go just as if it  wasn't  processed  by
  304.     APurify.
  305.  
  306.     You can disable/enable printing of messages by    making    a  call  to
  307.     AP_Report(flag). If  flag  is  true  (ie.  different  from  zero)  then
  308.     printing is enabled, if it is false (ie. equal to zero), no output will
  309.     be done. This is usefull for startup-codes. For  example,  if  you    are
  310.     using the argv[] array in C, APurify will make  a  lot  of    false-error
  311.     printing. This is because the values pointed by this array is allocated
  312.     before  the  library  is  opened.  You  can  avoid    this   by   calling
  313.     AP_Report(0) before, and AP_Report(1) after, the code that uses argv[].
  314.  
  315.     When debugging an APurify'ed program, you can put a  breakpoint  on
  316.     a function called AP_Err(). That function AP_Err() is called each  time
  317.     APurify detects an error. With that, you'll have the occasion  to  look
  318.     at your program just before a faultly memory-access occur.
  319.  
  320.     You can switch    from  a  verbose  output  to  a  shorter  one  with
  321.     AP_Verbose(flag). IF flag is true then the verbose mode is on. If it is
  322.     false then only short messages will be printed. Some people prefer    the
  323.     later so that is the default. If you perfer the verbose ouput then    put
  324.     AP_Verbose(1)  someware  in  your  code  and  you'll  get  some  longer
  325.     explanations about illegal accesses.
  326.  
  327.     You can specify a logfile where APurify can put its errors.  To  do
  328.     this, set the environment variable "APlog" (file env:APlog) to  a  name
  329.     of a logfile. If this variable is set, then APurify will append all its
  330.     outputs to the file indicated.
  331.  
  332.     You can use APurify on any  language  that  generates  a  temporary
  333.     assembly language sourcefile (included assembly itself :-) ). You  must
  334.     notice too, that you can use it on programs for which no source-code is
  335.     available (or .o files without .asm files). For  that,  use  a  program
  336.     that  can  do  reverse  engineering  on  your  executable    (ie:   that
  337.     disassembles the executable and  produces  a  .asm    file  ready  to  be
  338.     assembled). Then, with minor changes (prepend '_'  and  append  ':'  to
  339.     every interesting labels, put a call to AP_Init in    the  right  place),
  340.     you get a file ready to be processed by APurify. If the processed  file
  341.     has a HYNK_SYMBOL then you are very lucky and  you    need  not  work  on
  342.     labels. You then just have to find the "_main:" and add "jbsr _AP_Init"
  343.     as the first instruction of the "_main:" subroutine.
  344.  
  345.     Note: you can use ADIS on aminet to do reverse engineering (it seems to
  346.     be quite good a tool to do it).
  347.  
  348. EXAMPLE:
  349. -------
  350.     As an example, let's look at the test program. You'll see  how  you
  351.     can use the APurify report it produces to  find  what's  wrong  in  the
  352.     program. For this, I've included in that document the commented report.
  353.     My comments/explanations appear on lines beginning with a "#".
  354.  
  355.     **** APurify started on Tue Aug 22 22:27:18 1995
  356.  
  357.     #
  358.     # Well, the report started...
  359.     #
  360.  
  361.     **** APURIFY ERROR ! [$002908bc(4)  R--  (_main,  PC=$00279446  HUNK=$0
  362.     OFFSET=$23e)] accessed between:
  363.         -25     [$002908d8(27) RW- (_main*)]
  364.         +41     [$00286c48(40012) RW- (_main*)]
  365.  
  366.     # Hum... First hit... it is an error in reading something in the main()
  367.     # procedure between two blocks already  allocated.    The  nearest  block
  368.     # appears in first position, so we can think that the error was done by
  369.     # accessing an array allocated in main() with a negative index. We  can
  370.     # look at the code to find what is wrong with it. Using DOBJ, we  found
  371.     # at offset $23e in the first hunk the following code:
  372.     #
  373.     #        00.0000023e  4852               PEA.L   (A2)
  374.     #        00.00000240  4eb9 AP_WriteL        JSR       AP_WriteL
  375.     #        00.00000246  24ab ffd8           MOVE.L -40(A3),(A2)
  376.     #
  377.     # The  pointed  instruction  is  a    PEA  followed  by  a  JSR.  So    the
  378.     # interesting instruction is the third one. This corresponds to  the  C
  379.     # code:
  380.     #
  381.     #                   a[0]=b[-10]
  382.     #
  383.     # Hence we've discovered a first error in the code. Note  that  -25  is
  384.     # the distance (in bytes) between the end of the  accessed  memory  and
  385.     # the beginning of the array. This is not the  difference  between    the
  386.     # beginning address of the two blocks!
  387.     #
  388.  
  389.     **** APURIFY ERROR ! [$00283af8(4)  R--  (_main,  PC=$00279478  HUNK=$0
  390.     OFFSET=$270)] accessed between:
  391.         +1        [$00283ae8(16) RW- (_main*)]
  392.         -61     [$00283b38(412) RW- (_main*)]
  393.  
  394.     #
  395.     # Well... here it seems to be an access just after an allocated  block.
  396.     # the offset +1 is the distance in bytes between the accessed block and
  397.     # a allocated block. The situation is like this:
  398.     #
  399.     #              ---------[ 1 ]( 2 )---------->
  400.     #
  401.     # Where "[ 1 ]" is the allocated block and "( 2 )" the accessed  block.
  402.     # If we look in the code, we find:
  403.     #
  404.     #        00.00000270  4aaa 0004           TST.L   4(A2)
  405.     #
  406.     # that correponds to the test done by "if(a[1] == 0)". This is an error
  407.     # since the array 'a' is just 16-12=4 bytes long. So a[1] points out of
  408.     # the array!
  409.     #
  410.  
  411.     **** APURIFY ERROR !  [$00283af6(4)  R--  (_read_shifted,  PC=$00279302
  412.     HUNK=$0 OFFSET=$fa)] accessed across the ending boundary of:
  413.     -2    [$00283ae8(16) RW- (_main*)]
  414.  
  415.     #
  416.     # Hehe another error... That test program is a FULL of bug !  Yes,    but
  417.     # that one is an other kind of error. It is an access across a boundary
  418.     # That occur in the read_shifted() code. We need not look  in  the  asm
  419.     # file to see the error. Here it is a misaligment error. Visually  that
  420.     # gives:
  421.     #
  422.     #               ------------[ 1(]2 )----------->
  423.     #
  424.     #           [ 1 ] = allocated       ( 2 ) = accessed.
  425.     #
  426.  
  427.     ****  APURIFY  ERROR  !  [$00283af4(4)  R--  (_read_long,  PC=$00279332
  428.     HUNK=$0 OFFSET=$12a)] accessed between:
  429.         -65     [$00283b38(412) RW- (_main*)]
  430.         +11901  [$0027ec78(8192) RWS (standard stack frame of task)]
  431.  
  432.     #
  433.     # That error is strange! It is  not  an  access  to  an  array  with  a
  434.     # negative index as one think immediately: We never call read_long() in
  435.     # such a way. Indeed, the accessed memory  was  right  some  times    ago
  436.     # since is lays in the array 'a' (look at the second  hit).  Hence,  it
  437.     # must be an access to a freed memory. That  error    is  then  obviously
  438.     # found in the code:
  439.     #
  440.     #              free_arg(a); read_long(a).
  441.     #                   ^^^^^^^^^^^^
  442.     # NOTE: You can see that the program ran with a stack of 8192 bytes.
  443.     #
  444.  
  445.     **** APURIFY ERROR ! [$00000004(4) R--  (_read_page_zero,  PC=$00279396
  446.     HUNK=$0 OFFSET=$18e)] accessed on a read-protected block:
  447.         +4        [$00000000(1024) --S (Basic 680x0 vectors)]
  448.  
  449.     #
  450.     # Here the error is obvious, were are reading the zero-page. If it    was
  451.     # in writing, that error would be very dangerous.
  452.     #
  453.  
  454.     ****  APURIFY  WARNING  !  Closing    library  without  deallocation     of
  455.     the following block(s):
  456.         - [$00283b38(412) RW- (_main*)]
  457.         - [$00283d18(12012) RW- (_main*)]
  458.         - [$00286c48(40012) RW- (_main*)]
  459.  
  460.     #
  461.     # The program has exit()ed. APurify tells us that we've forget to  free
  462.     # those blocks. It    is  a  case  of  memory  leak.    Those  blocks  were
  463.     # allocated in main(). They appear in order of allocation.  Those  were
  464.     # allocated and lost by
  465.     #
  466.     #           a=malloc(4),malloc(400),malloc(12000),malloc(400000)
  467.     #
  468.     # since the ",,," returns the leftmost value.
  469.     #
  470.  
  471.     **** APurify ended on Tue Aug 22 22:27:18 1995
  472.  
  473.     #
  474.     # Well... done :-).
  475.     #
  476.  
  477.     NOTE: I hope this example is clear enough.. but I'm not sure.. tell  me
  478.     :^).
  479.  
  480. LEGAL PART:
  481. ----------
  482.     That program is provided 'AS IS'. I  am  not  responsible  for  any
  483.     dammage it can cause (but I am responsible for the benefits it can give
  484.     to you :-). Use that software at you own risks.
  485.  
  486.     That program is FREEWARE. You can use and distribute it as long  as
  487.     you keep the archive  intact  (no  adulteration  of  files  except  for
  488.     compression). It can't be sold without my agreement (except  a  minimal
  489.     amount for media support). You must ask me for commercial use  of  (any
  490.     part of) that product. I keep all my rights on  that  program  and    its
  491.     future releases. I can modify that software without telling it  to    the
  492.     users.
  493.  
  494.     If you wish, you can send me a postcard or anything else  you  want
  495.     (money, documentation, amiga, hardware  stuff,  ...)  in  exchange  for
  496.     using APurify. But there is no obligation :-). My postal address is:
  497.  
  498.         M. DEVULDER Samuel
  499.         1, Rue du chateau
  500.         59380 STEENE
  501.         FRANCE
  502.  
  503.     (yes I'm french !). You can  send  suggestions  or  bugs  to  my  email
  504.     address:
  505.  
  506.         devulder@info.unicaen.fr
  507.  
  508. DISTRIBUTION:
  509. ------------
  510.     That archive contains the english version of APurify:
  511.  
  512.     - doc/APurify.doc:     The file you are currently reading.
  513.     - doc/History:           The whole history.
  514.  
  515.     - bin/APurify:           The parser. Put it someware in your path.
  516.  
  517.     - lib/APur.a:           The link-time library. Put it someware in
  518.                    your library search-path.
  519.  
  520.     - test/test.c:           Source of a stupid test file.
  521.     - test/test:           Test file Apurify'ed.
  522.  
  523. NOTES:
  524. -----
  525.     My configuration is: one old A500 (1989), 2Mo RAM, 1  diskdrive,  1
  526.     HARD_DRIVE [300Mo, 10% full :-)], KS1.3 and a lot of  patience  (ah,  I
  527.     wish I had an A4000/040/33Mhz that does  not  meet    the  guru  all    the
  528.     time !).
  529.  
  530.     It has been compiled with cross-gcc 2.7.0  with  libnix  on  a    Sun
  531.     sparc.
  532.  
  533.     I had the idea of that program    after  a  chat    with  Cedric  BEUST
  534.     (AMIGA NEWS) on IRC (Internet Relay Chat). Thanks Cedric !
  535.  
  536.     I wish to thank Philippe Brand for his help  in  my  port.  He    was
  537.     really patient, even when I was really annoying (:-)). Thank you PHB !
  538.  
  539.     All marks are proprietary of their respective owners.
  540.  
  541.     There are some programs like APurify. For example,  FORTIFY  (Simon
  542.     P. Bullen), but  it  only  detects    illegal  writes  to  boundaries  of
  543.     allocated blocks. Thus it can't detect big oversteps and  oversteps  in
  544.     reading and the detection is not real-time. Enforcer can detect illegal
  545.     access to memory (I think), but it needs a special device (MMU).
  546.  
  547. HINTS & TIPS:
  548. ------------
  549.     You can see some memory leaks with that version of APurify.  It  is
  550.     not really good but it can help. Memory leak  occur  when  a  block  of
  551.     memory is nomore pointed by your  program.    Those  memory  blocks  will
  552.     necessary be displayed when your  program  exit()s.  So  with  all  the
  553.     messages printed on that occasion, you can find such  blocks.  I  known
  554.     this is not so great, but I think it can help you a little    bit  (maybe
  555.     in a future version I'll build some code to really check memory leaks).
  556.  
  557. BUGS:
  558. ----
  559.     APurify don't known public memory where a program can read or write
  560.     without having allocated it. Thus, it  will  report  an  error  when  a
  561.     program reads or writes values in a message obtained  through  GetMsg()
  562.     calls. Use AP_Report() to avoid such reports.
  563.  
  564.     It can display messages about closing the library  without  freeing
  565.     some memory blocks. This is due to printf() that allocates memory  that
  566.     is free'd on exit. This is not a real bug, but you can  avoid  this  by
  567.     doing a AP_Report(0) just before exiting. But you must notice  that  it
  568.     is better to display false bugs than to not display real ones.
  569.  
  570.     I've rewritten malloc()/realloc()/free().  I  hope  this  will  not
  571.     produce bugs (I've tested sucessfully the test program with  libnix and
  572.     ixemul, so I hope it will be all right).
  573.  
  574.     Certainly more bugs, but I'm waiting for your bug-reports.
  575.